package com.uxsino.commons.logicSelector;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

import com.alibaba.fastjson.annotation.JSONCreator;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonInclude(Include.NON_NULL)
public final class SelectorGroup<ObjectType> extends AbstractSelector<ObjectType> {

    public String name;

    @JsonProperty("group-by")
    @JSONField(name = "group-by")
    public GROUPBY_TYPE groupby;

    @JsonProperty("selectors")
    @JSONField(name = "selectors")
    private List<ISelector<ObjectType>> selectors;

    @JsonCreator
    @JSONCreator
    public SelectorGroup() {

    }

    public SelectorGroup(GROUPBY_TYPE groupby) {
        selectors = new ArrayList<>();
        this.groupby = groupby;
    }

    @Override
    public boolean _accept(SelectorContext<ObjectType> context) {

        for (ISelector<ObjectType> selector : selectors) {
            boolean r = selector.accept(context);

            switch (groupby) {
            case Any:
                if (r)
                    return true;
                break;
            case All:
                if (!r)
                    return false;
                break;
            case NoneOf:
                if (r)
                    return false;
            }
        }
        if (groupby.equals(GROUPBY_TYPE.Any)) {
            return false;
        }
        return true;
    }

    public void add(ISelector<ObjectType> sel) {
        selectors.add(sel);
    }

    public List<ISelector<ObjectType>> getSelectors() {
        return selectors;
    }

    @Override
    public boolean solveReference(Function<String, ISelector<ObjectType>> finder) {
        boolean solved = true;
        for (ISelector<ObjectType> sel : selectors) {
            solved = sel.solveReference(finder) && solved;
        }
        return solved;
    }

    @Override
    public String toString() {
        return "<selector " + (name == null ? "" : "name=\"" + name + "\" ") + "group-by=\"" + this.groupby + "\">";
    }

    @Override
    public String toXml() {
        String xml = "<selector " + (name == null ? "" : "name=\"" + name + "\" ") + "group-by=\"" + this.groupby
                + "\">";
        for (ISelector<ObjectType> sel : selectors) {
            xml += "\n" + sel.toXml();
        }
        xml += "</selector>";
        return xml;
    }

    @Override
    public String getSelectorTypeName() {
        return "selector";
    }
}
